﻿#pragma once

#include <learn/topo/topo_all.h>

namespace xi
{

namespace topo
{

class EXT_SYMBOL Half_Mesh
{
  public:
    /**
     * @brief 构造类型
     *
     */
    Half_Mesh() = default;

    /**
     * @brief 删除所有赋值和拷贝构造函数
     *
     */
    Half_Mesh(Half_Mesh &&) = delete;

    /**
     * @brief 析构
     *
     */
    virtual ~Half_Mesh();

    /**
     * @brief 判断是否为空
     *
     * @return true
     * @return false
     */
    bool empty() const;

    /**
     * @brief 获得顶点数
     *
     * @return std::size_t
     */
    std::size_t vertex_num() const;

    /**
     * @brief 获得面数
     *
     * @return std::size_t
     */
    std::size_t face_num() const;

    /**
     * @brief 获得半边数
     *
     * @return std::size_t
     */
    std::size_t coedge_num() const;

    /**
     * @brief 获得边数
     *
     * @return std::size_t
     */
    std::size_t edge_num() const;

    /**
     * @brief 顶点
     *
     * @return std::unordered_set<VHandle> &
     */
    std::unordered_set<VHandle> &vertices();

    /**
     * @brief 边
     *
     * @return std::unordered_set<EHandle> &
     */
    std::unordered_set<EHandle> &edges();

    /**
     * @brief coedge
     *
     * @return std::unordered_set<CHandle> &
     */
    std::unordered_set<CHandle> &coedges();

    /**
     * @brief 面
     *
     * @return std::unordered_set<FHandle> &
     */
    std::unordered_set<FHandle> &faces();

    /**
     * @brief 创建顶点，并返回指针（可选检查顶点是否重合，如果重合，返回重合顶点）
     *
     * @return VertexHandle
     */
    VHandle create_vertex();

    /**
     * @brief 创建边，返回与输入顶点顺序同向的 coedge
     *
     * @param[in] v1
     * @param[in] v2
     * @return CoedgeHandle
     */
    CHandle create_edge(VHandle v1, VHandle v2);

    /**
     * @brief 创建面并返回
     *
     * @param[in] es
     * @return FaceHandle
     */
    FHandle create_face(const std::vector<CHandle> &es);

    /**
     * @brief 删除顶点和相邻的面及其半边
     *
     * @param[in] v
     * @return true
     * @return false
     */
    bool remove(VHandle v);

    /**
     * @brief 删除边和相邻的面
     *
     * @param[in] e
     * @return true
     * @return false
     */
    bool remove(EHandle e);

    /**
     * @brief 删除面（只删除面）
     *
     * @param[in] f
     * @return true
     * @return false
     */
    bool remove(FHandle f);

    /**
     * @brief 删除孤立顶点
     *
     * @return true
     * @return false
     */
    bool remove_isolated_vertex();

    /**
     * @brief  删除孤立边
     *
     * @return true
     * @return false
     */
    bool remove_isolated_edge();

    /**
     * @brief  删除孤立面
     *
     * @return true
     * @return false
     */
    bool remove_isolated_face();

  protected:
    std::unordered_set<VHandle> m_vertices;
    std::unordered_set<EHandle> m_edges;
    std::unordered_set<CHandle> m_coedges;
    std::unordered_set<FHandle> m_faces;
};

class EXT_SYMBOL Half_Triangle_Mesh : public Half_Mesh
{
  public:
    /**
     * @brief 构造类型
     *
     */
    Half_Triangle_Mesh() = default;

    /**
     * @brief 删除所有赋值和拷贝构造函数
     *
     */
    Half_Triangle_Mesh(Half_Triangle_Mesh &&) = delete;

    /**
     * @brief 获得相对的顶点
     *
     * @param[in] co
     * @return VertexHandle
     */
    VHandle opposite_vertex(CHandle co) const;

    /**
     * @brief 获得面上顶点相对的 coedge
     *
     * @param[in] f
     * @param[in] v
     * @return CoedgeHandle
     */
    CHandle opposite_coedge(FHandle f, VHandle v) const;

    /**
     * @brief Delaunay 翻转边
     *
     * @param[in] e
     * @return true
     * @return false
     */
    bool flip_edge(EHandle e);
};

} // namespace topo

} // namespace xi
